package org.linlinjava.litemall.admin.job;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.beans.Constants;
import org.linlinjava.litemall.admin.beans.bo.AccessoryBo;
import org.linlinjava.litemall.admin.beans.bo.GoodsItemBo;
import org.linlinjava.litemall.admin.beans.bo.SpecificationBo;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.db.dao.LitemallSubscribeMapper;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.WebOrderGoodsRemarkDTO;
import org.linlinjava.litemall.db.dto.WxMemberSourceDTO;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderStatusUtil;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

import static org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_UNPAID;

/**
 * 订阅工作
 *
 * @author yliyun
 * @description：TODO
 * @date 2022/09/14
 */
//@Component
public class SubscribeJob {
    /**
     * 日志记录器
     */
    private final Log logger = LogFactory.getLog(SubscribeJob.class);

    /**
     * 订单服务
     */
    @Autowired
    private LitemallOrderService orderService;
    /**
     * litemall货物产品服务
     */
    @Autowired
    private LitemallGoodsProductService litemallGoodsProductService;
    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;
    /**
     * litemall订阅用户服务
     */
    @Autowired
    private LitemallSubscribeUserService litemallSubscribeUserService;
    /**
     * litemall商品服务
     */
    @Autowired
    private LitemallGoodsService litemallGoodsService;
    @Autowired
    private LumiereFormulaSpecificationsService lumiereFormulaSpecificationsService;

    @Autowired
    private  LumiereFormulaSpecificationsDataProportioningService lumiereFormulaSpecificationsDataProportioningService;
    @Autowired
    private LumiereFormulaMaterialService lumiereFormulaMaterialService;
    @Autowired
    private LitemallOrderFormulaMaterialService litemallOrderFormulaMaterialService;
    @Autowired
    private LitemallOrderGoodsPropertyService litemallOrderGoodsPropertyService;
    @Autowired
    private LitemallGoodsPropertyService goodsPropertyService;
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    /**
     * litemall地址服务
     */
    @Autowired
    private LitemallAddressService litemallAddressService;
    /**
     * litemall订货服务
     */
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;
    /**
     * litemall订货配件服务
     */
    @Autowired
    private LitemallOrderGoodsAccessoryService litemallOrderGoodsAccessoryService;
    /**
     * litemall店地区服务
     */
    @Autowired
    private LitemallShopRegionService litemallShopRegionService;
    /**
     * litemall税务服务
     */
    @Autowired
    private LitemallTaxService litemallTaxService;
    /**
     * litemall订阅产品服务
     */
    @Autowired
    private LitemallSubscribeGoodsService litemallSubscribeGoodsService;
    /**
     * litemall订阅产品价格服务
     */
    @Autowired
    private LitemallSubscribeGoodsPriceService litemallSubscribeGoodsPriceService;

    /**
     * litemall订单税务服务
     */
    @Autowired
    private LitemallOrderTaxService litemallOrderTaxService;
    /**
     * litemall商品配件服务
     */
    @Autowired
    private LitemallGoodsAccessoryService litemallGoodsAccessoryService;
    /**
     * litemall商店商品服务
     */
    @Autowired
    private LitemallShopMerchandiseService litemallShopMerchandiseService;
    /**
     * 注意助手
     */
    @Autowired
    private NoticeHelper noticeHelper;
    /**
     * litemall充电消费服务
     */
    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeConsumptionService;

    @Resource
    private LumiereSubscribeService lumiereSubscribeService;

    @Resource
    private LumiereSubscribeUserService lumiereSubscribeUserService;
    @Autowired
    private LumiereSubscirbeGoodsService lumiereSubscirbeGoodsService;
    @Resource
    private LumiereSubscribeRuleService lumiereSubscribeRuleService;
    @Autowired
    private LitemallAddressService addressService;

    /**
     * 订阅顺序
     * 每天凌晨三点点执行一次，在自动续订之后执行
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void subscribeOrder(){
        List<LitemallSubscribeUser> subscribeUsers = litemallSubscribeUserService.all();
        for(LitemallSubscribeUser item : subscribeUsers){
            if(checkSubscribOrder(item)){
                logger.info("auto handle subscribe start, id is :" + item.getId());
                LitemallGoods goods = litemallGoodsService.findById(item.getGoodsId());
                LitemallGoodsProduct goodsProduct = litemallGoodsProductService.findById(item.getGoodsProductId());
                String goodsItem = item.getGoodsItem();
                GoodsItemBo goodsItemBo = JSON.parseObject(goodsItem, GoodsItemBo.class);
                Integer orderId = autoSubmitOrder(item, goods, goodsProduct, goodsItemBo);
                try {
                    autoPayment(orderId, item);
                } catch (Exception e) {
                    e.printStackTrace();
                    autoPayFail(orderId, e.getMessage(), goods, item);
                }
            }
        }
    }

    /**
     * 自动确认生成订阅订单
     */
    //@Scheduled(cron = "0 0 0/1 * * ?")
    public void autoSubscribeOrder(){
        //拿到所有手动确认的订阅订单
        List<LumiereSubscribeUser> lumiereSubscribeUsers = lumiereSubscribeUserService.selectJoinList(LumiereSubscribeUser.class, new MPJLambdaWrapper<LumiereSubscribeUser>()
                .selectAll(LumiereSubscribeUser.class)
                .leftJoin(LumiereSubscribe.class, LumiereSubscribe::getId, LumiereSubscribeUser::getSubscribeId)
                .eq(LumiereSubscribe::getOrderRule, 1)
                .eq(LumiereSubscribeUser::getStatus, 1)
        );
        lumiereSubscribeUsers.stream().forEach(subscribeUser->{
            //当前用户的订阅规则
            LumiereSubscribeRule subscribeRule = lumiereSubscribeRuleService.findById(subscribeUser.getRuleId());
            LitemallUser litemallUser = userService.findById(subscribeUser.getUserId());
            int i=1;
            switch (subscribeRule.getRuleType()){
                //1按周
                case 1:
                    while (i<=subscribeRule.getDaysTimes()){
                        //创建订单
                        LitemallOrder litemallOrder = new LitemallOrder();
                        litemallOrder.setUserId(subscribeUser.getUserId());
                        litemallOrder.setShopId(subscribeUser.getShopId());
                        litemallOrder.setOrderSn(RandomUtil.randomNumbers(16));
                        litemallOrder.setSerialNo(orderService.getTodayMaxSerialNo(subscribeUser.getShopId())+1);
                        litemallOrder.setOrderStatus(Constants.ORDER_STATUS_NEW);
                        litemallOrder.setRefundStatus((byte) 0);
                        litemallOrder.setMadeStatus((byte) 0);

                        litemallOrder.setConsignee(litemallUser.getNickname());
                        litemallOrder.setMobile(litemallUser.getMobile());
                        //后期可以方法变更一下
                        litemallOrder.setAddress(litemallAddressService.findById(subscribeUser.getAddressId()).toString());
                        litemallOrder.setMessage(subscribeUser.getRemark());
                        litemallOrder.setGoodsPrice(subscribeUser.getPrice());
                        //配送费
                        litemallOrder.setFreightPrice(new BigDecimal(0));
                        litemallOrder.setCouponPrice(new BigDecimal(0));
                        litemallOrder.setGrouponPrice(new BigDecimal(0));
                        litemallOrder.setOrderPrice(subscribeUser.getPrice());
                        litemallOrder.setTaxPrice(subscribeUser.getTaxPrice());
                        litemallOrder.setActualPrice(subscribeUser.getTaxPrice());
                        litemallOrder.setCurrency("CAD");
                        litemallOrder.setOrderSource((byte) 4);
                        litemallOrder.setShipStatus((byte) 1);
                        litemallOrder.setReceiptStartTime(LocalDateTime.from(subscribeUser.getDeliveryStartTime()));
                        litemallOrder.setReceiptEndTime(LocalDateTime.from(subscribeUser.getDeliveryEndTime()));
                        litemallOrder.setShopOrder(true);
                        litemallOrder.setAddTime(LocalDateTime.now());
                        litemallOrder.setDeleted(false);
                        litemallOrder.setPoints(new BigDecimal(0.00));
                        litemallOrder.setMemberId(subscribeUser.getUserId());
                        litemallOrder.setMemberPrice(new BigDecimal(0.00));
                        litemallOrder.setGstPrice(new BigDecimal(0.00));
                        litemallOrder.setPstPrice(new BigDecimal(0.00));
                        litemallOrder.setHstPrice(new BigDecimal(0.00));
                        litemallOrder.setMemberPer(new BigDecimal(0.00));
                    }
                    break;
                //2按月
                case 2: break;
                //3按年
                case 3: break;
                default:
            }
        });
    }




    private LitemallOrder createOrder(LitemallSubscribeUser subscribeUser){
        Integer maxSerialNo = orderService.getTodayMaxSerialNo(subscribeUser.getShopId());
        LitemallUser posUser = userService.findById(subscribeUser.getUserId());
        LitemallOrder litemallOrder = new LitemallOrder();
        litemallOrder.setShopId(subscribeUser.getShopId());
        Integer addressId = subscribeUser.getAddressId();
        LitemallUser user = userService.findById(subscribeUser.getUserId());
        if(addressId != null){
            LitemallAddress address = litemallAddressService.findById(addressId);
            if(address != null){
                String addressStr = address.getCountry() + address.getProvince() + address.getCity() + address.getCounty() + address.getAddressDetail();
                litemallOrder.setAddress(addressStr);
                litemallOrder.setMobile(address.getTel());
                litemallOrder.setConsignee(user.getNickname());
            }
        }else{
            litemallOrder.setConsignee("");
            litemallOrder.setMobile("");
            litemallOrder.setAddress("");
        }
        litemallOrder.setUserId(subscribeUser.getUserId());
        litemallOrder.setEmployeeId(ObjectUtil.isNotNull(posUser) ? posUser.getUsername() : "");
        //litemallOrder.setOrderSn(RandomUtil.randomNumbers(16));
        litemallOrder.setSerialNo(maxSerialNo + 1);
        litemallOrder.setOrderSource(Constants.ORDER_SOURCE_SUBSCRIBE);
        litemallOrder.setOrderStatus(ORDER_STATUS_UNPAID);
        litemallOrder.setMadeStatus(org.linlinjava.litemall.db.beans.Constants.ORDER_MADE_STATUS_NEW);
        litemallOrder.setOrderType(subscribeUser.getDeliveryMethod());
        litemallOrder.setGoodsPrice(subscribeUser.getPrice());
        litemallOrder.setFreightPrice(BigDecimal.ZERO);
        //litemallOrder.setCouponPrice(orderGoodsCheckOut.getCouponPrice());
        litemallOrder.setIntegralPrice(BigDecimal.ZERO);
        litemallOrder.setOrderPrice(subscribeUser.getPrice());
        litemallOrder.setTaxPrice(subscribeUser.getTaxPrice());
        litemallOrder.setActualPrice(subscribeUser.getPrice());
        litemallOrder.setCurrency(DefaultCurType.CAD.getType());
        litemallOrder.setCouponPrice(new BigDecimal(0.00));
        litemallOrder.setPayTime(LocalDateTime.now());
        litemallOrder.setOrderSn(orderService.generateOrderSn(user.getId()));
        //litemallOrder.setPayType(reqVO.getPayType().byteValue());
        litemallOrder.setGstPrice(new BigDecimal(0.00));
        litemallOrder.setPstPrice(new BigDecimal(0.00));
        litemallOrder.setHstPrice(new BigDecimal(0.00));
        litemallOrder.setMemberPrice(new BigDecimal(0.00));
        litemallOrder.setMemberPer(new BigDecimal(0.00));
        litemallOrder.setSerinalNumber(orderService.getTodayMaxSerialNo(subscribeUser.getShopId()) + 1);
        litemallOrder.setShipStatus((byte) 1);
        litemallOrder.setMessage(subscribeUser.getRemark());
        litemallOrder.setDeleted(false);
        if (litemallOrder.getOrderType().byteValue() == org.linlinjava.litemall.db.beans.Constants.ORDER_SEND) {
            LitemallAddress checkedAddress = addressService.query(subscribeUser.getUserId(), subscribeUser.getAddressId());
            litemallOrder.setConsignee(checkedAddress.getName());
            litemallOrder.setMobile(checkedAddress.getTel());
            String detailedAddress = checkedAddress.getProvince() + checkedAddress.getCity() + checkedAddress.getCounty() + " " + checkedAddress.getAddressDetail();
            litemallOrder.setAddress(detailedAddress);
        }
        litemallOrder.setAddTime(LocalDateTime.now());
        litemallOrder.setReceiptStartTime(LocalDateTime.of(LocalDate.now(), subscribeUser.getDeliveryStartTime()));
        litemallOrder.setReceiptEndTime(LocalDateTime.of(LocalDate.now(), subscribeUser.getDeliveryEndTime()));
        litemallOrder.setExternalId(subscribeUser.getId());
        litemallOrder.setPayType(subscribeUser.getAutoPayType());
        orderService.save(litemallOrder);
        return litemallOrder;
    }

    private boolean createOrderGoods( LitemallGoodsProduct goodsProduct,List<Integer> orderGoodsIds,LitemallSubscribeUser subscribeUser, LitemallGoods goods, LitemallOrder litemallOrder) {

        // 根据商品ID获取商品信息
        LitemallGoods litemallGoods = litemallGoodsService.findById(goods.getId());
        LumiereSubscribeGoods subscribeGoods = lumiereSubscirbeGoodsService.findByGoodsIdAndSubId(goods.getId(), subscribeUser.getSubscribeId());

        // 创建订单商品对象
        LitemallOrderGoods litemallOrderGoods = new LitemallOrderGoods();
        litemallOrderGoods.setOrderId(litemallOrder.getId());
        litemallOrderGoods.setShopId(litemallOrder.getShopId());
        litemallOrderGoods.setGoodsName(litemallGoods.getName());
        litemallOrderGoods.setGoodsSn(litemallGoods.getGoodsSn());
        litemallOrderGoods.setCategoryId(litemallGoods.getCategoryId());
        litemallOrderGoods.setNumber(subscribeUser.getNumber().shortValue());
        litemallOrderGoods.setTaxPrice(subscribeUser.getTaxPrice());
        //litemallOrderGoods.setDiscountPrice(goods.getDiscountPrice());
        litemallOrderGoods.setGoodsId(litemallGoods.getId());

        //只有配方版
        LumiereFormulaSpecifications formulaSpecifications = lumiereFormulaSpecificationsService.getById(subscribeGoods.getSpecificationIds()[0]);
        String[] specifications = {formulaSpecifications.getSpecificationsName()};
        litemallOrderGoods.setSpecifications(specifications);
        Integer[] specificationIds = {formulaSpecifications.getId()};

        litemallOrderGoods.setUnitPrice(formulaSpecifications.getSpecificationsPrice());
        litemallOrderGoods.setSellingPrice(subscribeUser.getPrice());

        litemallOrderGoods.setSpecificationIds(specificationIds);
        litemallOrderGoods.setMadeStatus(org.linlinjava.litemall.db.beans.Constants.ORDER_MADE_STATUS_NEW);
        litemallOrderGoods.setPrice(subscribeUser.getPrice());
        litemallOrderGoods.setPicUrl(litemallGoods.getPicUrl());
        litemallOrderGoods.setAddTime(LocalDateTime.now());
        litemallOrderGoods.setUpdateTime(LocalDateTime.now());
        litemallOrderGoods.setDeleted(false);
        //制作下标
        List<WebOrderGoodsRemarkDTO> remarkList = new ArrayList<>();
        for (int i = 0; i < subscribeUser.getNumber(); i++) {
            remarkList.add(WebOrderGoodsRemarkDTO.builder().index(i).content("").indexMakeStatus(0).build());
        }
        litemallOrderGoods.setRemark(remarkList);
        // 将订单商品保存到数据库
        orderGoodsService.add(litemallOrderGoods);
        orderGoodsIds.add(litemallOrderGoods.getId());

        List<LitemallOrderFormulaMaterial> orderFormulaMaterials = new ArrayList<>();
        List<LumiereFormulaSpecificationsDataProportioning> formulaSpecificationsDataProportioningList = lumiereFormulaSpecificationsDataProportioningService.list(Wrappers.lambdaQuery(LumiereFormulaSpecificationsDataProportioning.class)
                .eq(LumiereFormulaSpecificationsDataProportioning::getFormulaSpecificationsId,formulaSpecifications.getId())
                .eq(LumiereFormulaSpecificationsDataProportioning::getIsDefault,1)
        );
        for (LumiereFormulaSpecificationsDataProportioning formulaSpecificationsDataProportioning : formulaSpecificationsDataProportioningList) {
            //原料
            LumiereFormulaMaterial formulaMaterial = lumiereFormulaMaterialService.getById(formulaSpecificationsDataProportioning.getFormulaMaterialId());
            //订单原料
            LitemallOrderFormulaMaterial orderFormulaMaterial = new LitemallOrderFormulaMaterial();
            orderFormulaMaterial.setOrderId(litemallOrder.getId());
            orderFormulaMaterial.setOrderGoodsId(litemallOrderGoods.getId());
            orderFormulaMaterial.setFormulaId(formulaSpecifications.getFormulaId());
            orderFormulaMaterial.setMaterialId(formulaMaterial.getMaterialId());
            orderFormulaMaterial.setMaterialName(formulaMaterial.getMaterialName());
            orderFormulaMaterial.setMakeUnit(formulaSpecificationsDataProportioning.getMakeUnit());
            orderFormulaMaterial.setSurcharge(formulaSpecificationsDataProportioning.getSurcharge());
            orderFormulaMaterial.setSpecificationsDose(formulaSpecificationsDataProportioning.getSpecificationsDose());
            orderFormulaMaterial.setQuantity(formulaSpecificationsDataProportioning.getQuantity());
            orderFormulaMaterial.setPrice(formulaSpecificationsDataProportioning.getPrice());
            orderFormulaMaterial.setUnit(formulaSpecificationsDataProportioning.getUnit());
            orderFormulaMaterial.setConsumeSystem(formulaSpecificationsDataProportioning.getConsumeSystem());
            orderFormulaMaterial.setMaterialType(formulaSpecificationsDataProportioning.getMaterialType());
            orderFormulaMaterial.setIsDefault(formulaSpecificationsDataProportioning.getIsDefault());
            orderFormulaMaterial.setAddTime(LocalDateTime.now());
            orderFormulaMaterial.setUpdateTime(LocalDateTime.now());
            orderFormulaMaterial.setDeleted(false);
            orderFormulaMaterials.add(orderFormulaMaterial);
        }
        if(CollUtil.isNotEmpty(orderFormulaMaterials)){
            litemallOrderFormulaMaterialService.saveBatch(orderFormulaMaterials);
        }

        List<LitemallGoodsProperty> goodsPropertyList = goodsPropertyService.queryByGoodsId(subscribeGoods.getGoodsId());
        // 遍历商品的属性列表，并保存到数据库
        for (LitemallGoodsProperty goodsProperty : goodsPropertyList) {
            if (ObjectUtil.isNotNull(goodsProperty)) {
                LitemallOrderGoodsProperty orderGoodsProperty = new LitemallOrderGoodsProperty();
                orderGoodsProperty.setOrderId(litemallOrder.getId());
                orderGoodsProperty.setOrderGoodsId(litemallOrderGoods.getId());
                orderGoodsProperty.setGoodsId(litemallGoods.getId());
                orderGoodsProperty.setGoodsPropertyId(goodsProperty.getId());
                orderGoodsProperty.setName(goodsProperty.getName());
                orderGoodsProperty.setValue(goodsProperty.getIsDefault());
                orderGoodsProperty.setAddTime(LocalDateTime.now());
                orderGoodsProperty.setDeleted(false);
                litemallOrderGoodsPropertyService.add(orderGoodsProperty);
            }
        }

        // 遍历商品的税费列表，并保存到数据库
        List<LitemallShopRegion> shopRegions = litemallShopRegionService.queryByShopId(subscribeUser.getShopId());
        List<LitemallTax> litemallTaxes = litemallTaxService.queryByRegionIds(shopRegions.stream().map(LitemallShopRegion::getRegionId).collect(Collectors.toList()));
        BigDecimal tax = new BigDecimal(0.00);
        List<Integer> taxTypes = new ArrayList<>(Arrays.asList(goodsProduct.getTaxTypes()));
        BigDecimal subGoodsPrice = getSubGoodsPrice(subscribeGoods.getId(), subscribeUser.getUserId(), subscribeUser.getNumber());
        for(LitemallTax item : litemallTaxes){
            boolean anyMatch = taxTypes.stream().anyMatch(type -> {
                return type == item.getType().intValue();
            });
            if(anyMatch){
                //计算税价
                tax = tax.add(item.getValue().divide(new BigDecimal(100.00)));
                /**
                 * 记录订单税费项
                 */
                LitemallOrderTax orderTax = new LitemallOrderTax();
                orderTax.setCode(item.getCode());
                orderTax.setName(item.getName());
                orderTax.setType(item.getType());
                orderTax.setValue(item.getValue());
                orderTax.setGoodsId(subscribeGoods.getGoodsId());
                orderTax.setPrice(tax.multiply(subGoodsPrice));
                orderTax.setOrderGoodsId(litemallOrderGoods.getId());
                litemallOrderTaxService.add(orderTax);
            }
        }
        return true;
    }


    /**
     * 自动提交订单
     * 自动下订单
     *
     * @param subscribeUser 订阅用户
     * @param goods         货物
     * @param goodsProduct  商品产品
     * @param goodsItemBo   商品项波
     * @return {@link Integer}
     */
    @Transactional
    public Integer autoSubmitOrder(LitemallSubscribeUser subscribeUser, LitemallGoods goods, LitemallGoodsProduct goodsProduct, GoodsItemBo goodsItemBo){
        LitemallOrder submitOrder = createOrder(subscribeUser);
        List<Integer> orderGoodsIds = new ArrayList<>();
        createOrderGoods(goodsProduct,orderGoodsIds,subscribeUser,goods,submitOrder);
        return submitOrder.getId();
    }

    /**
     * 自动付款
     * 自动支付订单，目前仅支持余额支付
     *
     * @param orderId       订单id
     * @param subscribeUser 订阅用户
     * @throws Exception 异常
     */
    @Transactional
    public void autoPayment(Integer orderId, LitemallSubscribeUser subscribeUser) throws Exception{
        LitemallOrder order = orderService.findById(orderId);
        // 检测订单是否能够支付
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isPay()) {
            throw new RuntimeException("订单不能支付");
        }

        LitemallUser user = userService.findById(subscribeUser.getUserId());
        if(user == null){
            throw new RuntimeException("订单不能支付");
        }
        if(user.getAvailableAmount().compareTo(order.getActualPrice()) < 1){
            throw new RuntimeException("用户余额不足");
        }

        if(subscribeUser.getAutoPayType() == Constants.PAY_TYPE_BALANCE){
            LitemallRechargeConsumption litemallRechargeConsumption = saveLog(order, user, Constants.LOG_GIFTCARD_CONSUME);

            order.setPayType(Constants.PAY_TYPE_BALANCE);
            order.setCurrency(DefaultCurType.CAD.getType());
            order.setPayTime(LocalDateTime.now());
//            order.setOrderStatus(OrderUtil.STATUS_PAY);
            order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);//订单状态修改为“进行中”
        	order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//制作状态为“待制作”
            order.setPayId(String.valueOf(litemallRechargeConsumption.getId()));        //将消费日志id作为支付id
            order.setTransationId(String.valueOf(litemallRechargeConsumption.getId())); //将消费日志id作为transation id
            orderService.updateById(order);
            //更新订单
            /*if (orderService.updateWithOptimisticLocker(order) == 0) {
                // 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
                // 如果数据库首先因为系统自动取消订单而更新了订单状态；
                // 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
                // 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
                order = orderService.findBySn(order.getOrderSn());
                int updated = 0;
                if (OrderUtil.isAutoCancelStatus(order)) {
                    order.setPayTime(LocalDateTime.now());
//                    order.setOrderStatus(OrderUtil.STATUS_PAY);
                    order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);//订单状态修改为“进行中”
                	order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//制作状态为“待制作”
                    updated = orderService.updateWithOptimisticLocker(order);
                }

                // 如果updated是0，那么数据库更新失败
                if (updated == 0) {
                    throw new RuntimeException("订单不能支付");
                }
            }*/

            //更新用户余额
            LitemallUser update = new LitemallUser();
            update.setId(user.getId());
            update.setAvailableAmount(user.getAvailableAmount().subtract(order.getActualPrice()));
            userService.updateWithOptimisticLocker(update, user.getUpdateTime());
        }else{
            /**
             * TODO 其他方式支付
             */
            throw new RuntimeException("暂不支持的支付方式");
        }


        //发送订单支付成功通知
        noticeHelper.noticeUser(org.linlinjava.litemall.db.beans.Constants.MSG_TYPE_ORDER,"订阅订单", order.getOrderSn()+"订单自动支付成功", subscribeUser.getUserId(), order);
        //发送已支付订单到pos系统，门店开始制作商品
        noticeHelper.noticeShop(org.linlinjava.litemall.db.beans.Constants.MSG_TYPE_ORDER, JSON.toJSONString(order), order.getShopId());
        //发送邮件通知
        LitemallGoods goods = litemallGoodsService.findById(subscribeUser.getGoodsId());
        noticeHelper.notifyMailTemplate("subscribe payment", NotifyType.SUBSCRIBE_PAY_SUCCEED, user.getEmail(), new String[]{goods.getName()});
    }

    /**
     * 汽车支付失败
     *
     * @param orderId     订单id
     * @param description 描述
     * @param goods       货物
     * @param item        项
     */
    public void autoPayFail(Integer orderId, String description, LitemallGoods goods, LitemallSubscribeUser item){
        LitemallOrder order = orderService.findById(orderId);
        LitemallOrder update = new LitemallOrder();
        update.setId(orderId);
        update.setDescription(description);
        orderService.updateById(update);
        noticeHelper.noticeUser(org.linlinjava.litemall.db.beans.Constants.MSG_TYPE_ORDER,"订阅订单", order.getOrderSn()+"订单自动支付失败，请手动支付", order.getUserId(), order);
        //发送邮件通知
        LitemallUser user = userService.findById(item.getUserId());
        noticeHelper.notifyMailTemplate("订阅订单", NotifyType.SUBSCRIBE_PAY_ERROR, user.getEmail(), new String[]{goods.getName()});
    }

    /**
     * 得到子商品价格
     * 根据用户和数量获取订阅价格
     *
     * @param subscribeGoodsId 订阅产品id
     * @param userId           用户id
     * @param number           数量
     * @return {@link BigDecimal}
     */
    public BigDecimal getSubGoodsPrice(Integer subscribeGoodsId, Integer userId, Integer number){
        LitemallSubscribeGoods subscribeGoods = litemallSubscribeGoodsService.findById(subscribeGoodsId);
        List<LitemallSubscribeGoodsPrice> subscribeGoodsPrices = litemallSubscribeGoodsPriceService.queryBySubGoodsId(subscribeGoodsId);
        if(subscribeGoodsPrices != null && subscribeGoodsPrices.size() > 0){
            LitemallUser user = userService.findById(userId);
            List<LitemallSubscribeGoodsPrice> collect = subscribeGoodsPrices.stream().filter(item -> {
                return item.getUserLevel() == null || item.getUserLevel() == user.getUserLevel();
            }).collect(Collectors.toList());
            if(collect != null && collect.size() > 0){
                /**
                 * 将数据按数量倒叙
                 */
                List<LitemallSubscribeGoodsPrice> sortedSubGoods = collect.stream().sorted(Comparator.comparing(LitemallSubscribeGoodsPrice::getNumber).reversed()).collect(Collectors.toList());
                /**
                 * 取最接近的数量的价格,如果没有则取设置的最少数量对应的价格
                 */
                if(number == null || (sortedSubGoods.get(sortedSubGoods.size() -1).getNumber() != null && sortedSubGoods.get(sortedSubGoods.size() -1).getNumber() < number)){
                    return sortedSubGoods.get(sortedSubGoods.size() -1).getPrice();
                }else{
                    for(LitemallSubscribeGoodsPrice i : sortedSubGoods){
                        if(i.getNumber() != null && number > i.getNumber()){
                            return i.getPrice();
                        }
                    }
                }
            }
        }
        return subscribeGoods.getBasePrice();

    }

    /**
     * 检查subscrib秩序
     * 检查订阅是否可自动下单
     *
     * @param subscribeUser 订阅用户
     * @return {@link Boolean}
     */
    public Boolean checkSubscribOrder(LitemallSubscribeUser subscribeUser){
        Boolean rtn = false;
        Byte method = subscribeUser.getMethod();
        Integer deliveryDays = subscribeUser.getDeliveryDays();
        LocalDateTime startTime = subscribeUser.getStartTime();
        LocalDateTime endTime = subscribeUser.getEndTime();
        /**
         * 检查时间
         */
        if(startTime.isBefore(LocalDateTime.now()) && endTime.isAfter(LocalDateTime.now())){
            if(method == Constants.SUBSCRIBE_METHOD_YEAR){
                int dayOfMonth = LocalDate.now().getDayOfMonth();
                if(deliveryDays == dayOfMonth){
                    rtn =  true;
                }
            }else if(method == Constants.SUBSCRIBE_METHOD_MONTH){
                int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
                if(deliveryDays == dayOfWeek){
                    rtn = true;
                }
            }else if(method == Constants.SUBSCRIBE_METHOD_WEEK){
                rtn = true;
            }
        }
        /**
         * 检查今天是否已经下过单了
         */
        if(orderService.countTodayByExtendId(subscribeUser.getId()) > 0){
            rtn = false;
        }
        return rtn;
    }

    /**
     * 保存日志
     * 记录日志并返回
     *
     * @param order 订单
     * @param user  用户
     * @param type  类型
     * @return {@link LitemallRechargeConsumption}
     */
    @Transactional
    public LitemallRechargeConsumption saveLog(LitemallOrder order, LitemallUser user, Byte type){
        LitemallRechargeConsumption log = new LitemallRechargeConsumption();
        log.setAmount(order.getActualPrice());
        log.setOrderId(order.getId());
        log.setAddUserId(user.getId());
        log.setUserId(user.getId());
        log.setUsername(user.getUsername());
        log.setMobile(user.getMobile());
        log.setPoints(user.getPoints());
        log.setType(type);
        log.setUserLevel(user.getUserLevel());
        log.setAvailableAmount(user.getAvailableAmount().subtract(order.getActualPrice()));
        log.setOrderSource(org.linlinjava.litemall.db.beans.Constants.ORDER_SOURCE_APP);
        litemallRechargeConsumptionService.add(log);
        return log;
    }
}
